﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Pear.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace Pear.Application.UserCenter
{
    /// <summary>
    /// 部门服务
    /// </summary>
    [ApiDescriptionSettings(ApiGroupConsts.USER_CENTER)]
    public class DepartmentService : IDepartmentService, IDynamicApiController, ITransient
    {
        /// <summary>
        /// 部门仓储
        /// </summary>
        private readonly IRepository<Department> _deptRepository;

        /// <summary>
        /// 用户仓储
        /// </summary>
        private readonly IRepository<User> _userRepository;



        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="deptRepository"></param>
        /// <param name="userRepository"></param>
        public DepartmentService(IRepository<Department> deptRepository
            , IRepository<User> userRepository)
        {
            _deptRepository = deptRepository;
            _userRepository = userRepository;
        }


        /// <summary>
        /// 获取所有部门列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine("admin.usercenter.dept:view"), HttpGet, ApiDescriptionSettings(Name = "list")]
        public async Task<PagedList<DepartmentProfile>> GetListAsync([FromQuery, Required] GetDepartmentListInput input)
        {
            var hasKeyword = !string.IsNullOrEmpty(input.Keyword?.Trim());

            var departments = await _deptRepository.Where(
                                                (hasKeyword, u => EF.Functions.Like(u.Name, $"%{input.Keyword.Trim()}%")),
                                                (hasKeyword, u => EF.Functions.Like(u.Remark, $"%{input.Keyword.Trim()}%"))
                                              )
                                             .OrderBy(u => u.Sequence)
                                             .ToPagedListAsync(input.PageIndex, input.PageSize);

            return departments.Adapt<PagedList<DepartmentProfile>>();
        }

        /// <summary>
        /// 获取所有部门列表（不分页）
        /// </summary>
        /// <returns></returns>
        [SecurityDefine("admin.usercenter.dept:view"), HttpGet, ApiDescriptionSettings(Name = "all")]
        public async Task<List<DepartmentProfile>> GetAllAsync()
        {
            var departments = await _deptRepository.Where(u => u.Id > 0).OrderBy(u => u.Sequence).ToListAsync();
            return departments.Adapt<List<DepartmentProfile>>();
        }




        /// <summary>
        /// 获取部门实体
        /// </summary>
        /// <param name="departmentId">部门编号</param>
        /// <returns></returns>
        [SecurityDefine("admin.usercenter.dept:view"), HttpGet]
        public async Task<DepartmentProfile> ProfileAsync([Required, Range(1, int.MaxValue, ErrorMessage = "请输入有效的部门 Id")] int departmentId)
        {
            // 查询部门是否存在
            var department = await _deptRepository.FirstOrDefaultAsync(u => u.Id == departmentId, false);
            return department.Adapt<DepartmentProfile>();
        }



        /// <summary>
        /// 修改部门
        /// </summary>
        /// <param name="departmentId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine("admin.usercenter.dept:edit")]
        public async Task ModifyAsync([Required, Range(1, int.MaxValue, ErrorMessage = "请输入有效的部门 Id"), ApiSeat(ApiSeats.ActionStart)] int departmentId, [Required] EditDepartmentInput input)
        {
            // 查询菜单是否存在
            var isExist = await _deptRepository.AnyAsync(u => u.Id == departmentId, false);
            if (!isExist) throw Oops.Oh(SystemErrorCodes.u1002);

            var modifyDepartment = input.Adapt<Department>();

            // 配置主键和更新时间
            modifyDepartment.Id = departmentId;
            modifyDepartment.UpdatedTime = DateTimeOffset.Now;

            await _deptRepository.UpdateExcludeAsync(modifyDepartment, new[] { nameof(Role.IsDeleted), nameof(Role.CreatedTime) }, ignoreNullValues: true);
        }

        /// <summary>
        /// 改变部门状态
        /// </summary>
        /// <param name="departmentId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine("admin.usercenter.dept:edit"), HttpPost]
        public async Task ChangeEnabledAsync([Required, Range(1, int.MaxValue, ErrorMessage = "请输入有效的部门 Id"), ApiSeat(ApiSeats.ActionStart)] int departmentId, [Required] ChangeEnabledInput input)
        {
            // 查询角色是否存在
            var isExist = await _deptRepository.AnyAsync(u => u.Id == departmentId, false);
            if (!isExist) throw Oops.Oh(SystemErrorCodes.u1002);

            var modifyDepartment = input.Adapt<Department>();

            // 配置主键和更新时间
            modifyDepartment.Id = departmentId;
            modifyDepartment.UpdatedTime = DateTimeOffset.Now;

            await _deptRepository.UpdateExcludeAsync(modifyDepartment, new[] { nameof(Department.IsDeleted), nameof(Department.CreatedTime) }, ignoreNullValues: true);
        }


        /// <summary>
        /// 新增部门
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [ApiDescriptionSettings(KeepVerb = true), SecurityDefine("admin.usercenter.dept:add")]
        public async Task<DepartmentProfile> AddAsync([Required] EditDepartmentInput input)
        {
            // 判断部门是否存在
            var isExist = await _deptRepository.AnyAsync(u => u.Name.Trim().Equals(input.Name.Trim()));
            if (isExist) throw Oops.Oh(SystemErrorCodes.u1006);

            var addDepartment = input.Adapt<Department>();

            var entryEntity = await _deptRepository.InsertNowAsync(addDepartment);
            return entryEntity.Entity.Adapt<DepartmentProfile>();
        }



        /// <summary>
        /// 删除部门
        /// </summary>
        /// <param name="departmentId"></param>
        /// <returns></returns>
        [SecurityDefine("admin.usercenter.dept:delete")]
        public async Task DeleteAsync([Required, Range(1, int.MaxValue, ErrorMessage = "请输入有效的部门 Id"), ApiSeat(ApiSeats.ActionStart)] int departmentId)
        {
            // 查询部门是否存在
            var deleteDepartment = await _deptRepository.FindAsync(departmentId);
            _ = deleteDepartment ?? throw Oops.Oh(SystemErrorCodes.u1002);

            // 查询部门是否被其他数据引用
            var isRef = await _deptRepository.Include(u => u.Sublevels, false)
                                                 .Include(u => u.Users)
                                                 .AnyAsync(u => u.Id == departmentId && (u.Sublevels.Any() || u.Users.Any()));

            if (isRef) throw Oops.Oh(SystemErrorCodes.u1007);

            // 软/假删除
            deleteDepartment.UpdatedTime = DateTimeOffset.Now;
            deleteDepartment.IsDeleted = true;
        }


    }
}